/*
* Conditions Of Use
*
* This software was developed by employees of the Sigmatrix(Beijing) Corporation.
* This software is provided by sigmatrix as a service and is expressly
* provided "AS IS."  Sigmatrix MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
* AND DATA ACCURACY.  Sigmatrix does not warrant or make any representations
* regarding the use of the software or the results thereof, including but
* not limited to the correctness, accuracy, reliability or usefulness of
* the software.
*
* Permission to use this software is contingent upon your acceptance
* of the terms of this agreement.
*
*/
package com.sigmatrix.h5.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;
import com.sigmatrix.h5.dao.WarehouseStockDao;
import com.sigmatrix.h5.dao.WarehouseStockDetailsDao;
import com.sigmatrix.h5.dto.ProductData;
import com.sigmatrix.h5.entity.FirstLevelQRCode;
import com.sigmatrix.h5.entity.MultistageLevelQRCode;
import com.sigmatrix.h5.entity.WarehouseStock;
import com.sigmatrix.h5.entity.WarehouseStockDetails;
import com.sigmatrix.h5.exception.DaoException;
import com.sigmatrix.h5.exception.ServiceException;
import com.sigmatrix.h5.service.ProductService;
import com.sigmatrix.h5.service.WarehouseStockService;
import com.sigmatrix.h5.service.common.impl.BaseServiceImpl;
import com.sigmatrix.h5.utils.Cons;
import com.sigmatrix.h5.utils.QRCodeUtil;
import com.sigmatrix.h5.utils.Utils;
import com.sigmatrix.h5.web.vo.OutStorageVo;

/**
 * @ClassName: WarehouseStockServiceImpl
 * @Description: 库存信息业务层接口
 * @author youjun 
 * @date 2017-06-14 09:50:39
 */
@Service(value="warehouseStockService")
public class WarehouseStockServiceImpl extends BaseServiceImpl<WarehouseStock> implements WarehouseStockService {

	/**logger record*/
	private static final Logger LOGGER = LoggerFactory.getLogger(WarehouseStockServiceImpl.class);
	
	/** 库存信息数据库操作接口 */
	@Autowired
	private transient WarehouseStockDao warehouseStockDao;
	
	/**产品业务层接口*/
	@Autowired
	private transient ProductService productService;
	
	@Autowired
	private transient WarehouseStockDetailsDao warehouseStockDetailsDao;

	/**(non-Javadoc)
	 *@Title: reduceStockNum
	 *@Description: 
	 *@see com.sigmatrix.sc.handheld.inter.service.WarehouseStockService#reduceStockNum(int, int, java.lang.String, int, int, java.lang.String)
	 *@author youjun
	 *@date 2017年8月13日 下午3:23:31
	 */
	@Override
	public String reduceStockNum(final int warehouseId, final int productId, 
			final int singleCount, final int packCount, final String enterpriseCode) throws ServiceException {
		
		// 先进行查询:1、验证是否存在,2、库存是否足够
		final WarehouseStock warehouseStockCondition = new WarehouseStock();
		warehouseStockCondition.setWarehouseId(warehouseId);
		warehouseStockCondition.setProductId(productId);
		try {
			final List<WarehouseStock> stockList = warehouseStockDao.findListByCondition(warehouseStockCondition, enterpriseCode);
			if(CollectionUtils.isEmpty(stockList)) {
				return "库存不存在";
			}
			if(stockList.size()!=2){
				return "同一个仓库的同一个产品必须存在2个库存记录(单品码一个库存，包装码一个库存)";
			}
			final WarehouseStock warehouseStock = stockList.get(0);
			// 验证库存是否足够
			int numOfBox = 0;
			int numOfSp = 0;
			if(warehouseStock.getLevel()>1) {
				numOfBox = warehouseStock.getNumber();
				numOfSp = stockList.get(1).getNumber();
			}else{
				numOfSp = warehouseStock.getNumber();
				numOfBox = stockList.get(1).getNumber();
			}
			int actualReduceBoxCount = packCount; // 实际减少箱数
			int changeSpCount = numOfSp-singleCount; // 改变成的瓶数
			if(numOfBox<packCount){
				return "库存包装单位数量小于出库数量";
			}
			int splitBoxNum = 0; // 若单品数量不够减,需拆箱数
			final ProductData product = productService.findById(productId, enterpriseCode);
			if(numOfSp<singleCount) { // 拆箱
				// 判断瓶数
				// 箱（包装单位）拥有的瓶（单品单位）数
				int boxHaveSpCount = productService.getCountHaveSpecifiedLevelCount(product, product.getProductUnit(), 1);
				if((numOfBox-packCount)*boxHaveSpCount+numOfSp<singleCount) { // 仍然小于,说明库存不足
					return "库存不足";
				}
				// 计算需要拆除的箱数
				for(int i=1;i<=numOfBox-packCount;i++) {
					if(numOfSp+boxHaveSpCount*i>=singleCount) {
						splitBoxNum = i;
						break;
					}
				}
				// 更改actualReduceBoxCount、changeSpCount
				actualReduceBoxCount = packCount + packCount;
				changeSpCount = numOfSp+boxHaveSpCount*splitBoxNum-singleCount;
			}
			// 更新单品库存
			int result = warehouseStockDao.reduceStockNum(productId, warehouseId, changeSpCount, Cons.PACK_LEVEL_ONE, enterpriseCode);
			if(result<=0) {
				return "库存更新失败";
			}
			// 更新包装库存
			result = warehouseStockDao.reduceStockNum(productId, warehouseId, actualReduceBoxCount, product.getProductUnit().intValue(), enterpriseCode);
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
		return Cons.SUCCESS_MESSAGE;
	}
	
	@Override
	public String addStockNum(int toWarehouseId, int productId, int singleCount, int packCount,List<MultistageLevelQRCode> outPackLevelCodeList, 
			List<FirstLevelQRCode> outSingleLevelCodeList,OutStorageVo outStorageVo,String enterpriseCode)
			throws ServiceException {
		// 更新库存详情的包装码状态
		// 从出库的包装码集合中按产品、批次找出对应的包装码
		final List<String> boxList = QRCodeUtil.classificationByProductId(outPackLevelCodeList, null, productId);
		@SuppressWarnings("unused")
		final List<String> singleList = QRCodeUtil.classificationByProductId(null, outSingleLevelCodeList, productId);
		final ProductData product = productService.findById(productId, enterpriseCode);
		final Short productUnit = product.getProductUnit();//产品包装级别
		Integer packlevel= 0; //产品包装级别
		if (Utils.isNotEmpty(productUnit)) {
			packlevel = Integer.valueOf(productUnit+"");
		}
		Long stockId = null;//主库存Id
		Integer number = 0;//库存数量
		try {
			//判断主库存是否存在  （如果存在，更新明细，统计后更新主库存数量；不存在，创建一条，更新明细，统计后更新库存数量）
			final List<WarehouseStock> list = warehouseStockDao.findByCondition(enterpriseCode, toWarehouseId, productId, packlevel);
			if(Utils.isNotEmpty(list)){
				final WarehouseStock stock = list.get(0);
				stockId = stock.getId();
				number = packCount + stock.getNumber();
				//更新主库存单（数据）
				warehouseStockDao.updateNumById(enterpriseCode, stockId, number);
				LOGGER.info("更新主库存数量={}",number);
			}else{
				WarehouseStock wStock = new WarehouseStock();
				wStock.setLevel(packlevel);
				wStock.setProductId(productId);
				wStock.setProductCode(product.getProductCode());
				wStock.setWarehouseId(toWarehouseId);
				wStock.setNumber(packCount);
				stockId = warehouseStockDao.insert(enterpriseCode, wStock);
				LOGGER.info("创建成功主库存单包装级别数据："+JSONObject.toJSONString(wStock));
			}
			//库存明细  每个码一条记录
			if (Utils.isNotEmpty(boxList)) {
				final List<WarehouseStockDetails> wStockList = new ArrayList<WarehouseStockDetails>();
				for (String code : boxList) {
					WarehouseStockDetails detail = new WarehouseStockDetails();
					detail.setStockId(stockId);//主库存Id
					detail.setCode(code);//码内容
					detail.setStatus(Cons.WH_STOCK_DETAILS_STATUS_IN_STORAGE);//在库
					detail.setCreateTime(new Date());//当前时间
					detail.setCreatorId(outStorageVo.getUserId());//用户userId
					wStockList.add(detail);
				}
				//批量插入明细表
				warehouseStockDetailsDao.batchSave(wStockList, enterpriseCode);
				
			}
			
			//暂时不支持按瓶出库
			final List<WarehouseStock> listOne = warehouseStockDao.findByCondition(enterpriseCode, toWarehouseId, productId, Cons.PACK_LEVEL_ONE);
			if (Utils.isEmpty(listOne)) {
				LOGGER.info("主库存单品级别数据为空自动创建一条记录，分销销售出库对主库存条数有要求");
				WarehouseStock wStock = new WarehouseStock();
				wStock.setLevel(Cons.PACK_LEVEL_ONE);
				wStock.setProductId(productId);
				wStock.setProductCode(product.getProductCode());
				wStock.setWarehouseId(toWarehouseId);
				wStock.setNumber(0);
				warehouseStockDao.insert(enterpriseCode, wStock);
				LOGGER.info("创建成功主库存单品级别数据："+JSONObject.toJSONString(wStock));
			}
			

		} catch (DaoException e) {
			throw new ServiceException(e);
		}
		return Cons.SUCCESS_MESSAGE;
	}

	/**
	 * (non-Javadoc)
	 *@Title: addStockNum
	 *@Description: 
	 *@see com.sigmatrix.sc.handheld.inter.service.WarehouseStockService#addStockNum(int, int, java.lang.String, int, int, java.lang.String)
	 *@author youjun
	 *@date 2017年8月15日 上午1:27:33
	 */
	@Override
	public String addStockNum(final int warehouseId, final int productId, final String batchCode, 
			final int singleCount, final int packCount, final String enterpriseCode) throws ServiceException {
		
		// 先进行查询:1、验证是否存在,不存在新增 2、存在update数量
		final WarehouseStock warehouseStockCondition = new WarehouseStock();
		warehouseStockCondition.setWarehouseId(warehouseId);
		warehouseStockCondition.setProductId(productId);
		try {
			final List<WarehouseStock> stockList = warehouseStockDao.findListByCondition(warehouseStockCondition, enterpriseCode);
			if(CollectionUtils.isEmpty(stockList)) {
				final WarehouseStock warehouseStock = new WarehouseStock();
//				warehouseStock.setNumOfBox(packCount); // 库存箱数
//				warehouseStock.setNumOfSp(singleCount); // 库存瓶数
				warehouseStock.setProductId(productId); // 产品ID
				warehouseStock.setWarehouseId(warehouseId); // 仓库ID
				warehouseStockDao.save(warehouseStock, enterpriseCode);
				return Cons.SUCCESS_MESSAGE;
			}
			if(stockList.size()>1){
				return "同一个仓库的同一个产品的同一个批次存在多个库存记录";
			}
			final int result = warehouseStockDao.addStockNum(productId, warehouseId, batchCode, singleCount, packCount, enterpriseCode);
			if(result<=0) {
				return "库存更新失败";
			}
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
		return Cons.SUCCESS_MESSAGE;
	}


}
